/*
 * 本example主要是用来展示如何使用DGGSKernel库实现格网编码与经纬度的相互转化、格网的拓扑查询等
 * 主要使用到IDGGSKernel.hpp
 * */

#include"IDGGSKernel.hpp"
#include"MathDefine.hpp"

// 本样例使用的变量方法均定义在NNU::DGGS::Kernel命令空间内
// 基础的数据结构定义在NNU::DGGS::Base命名空间内
using namespace NNU::DGGS::Kernel;
using namespace NNU::DGGS::Base;
using namespace NNU::DGGS;

/// <summary>
/// 编码转经纬度，使用IDGGSKernel的decode方法
/// </summary>
/// <param name="code">格网编码</param>
/// <param name="coord">经纬度结构体</param>
/// <param name="gridType">格网类型</param>
void decode(DGGSElementCode code, GeoCoord &coord, DGGSGridType gridType)
{
    // 初始化结构体，参数为格网类型：DGGS_ISEA4H,DGGS_ISEA4T,DGGS_ISEA4D
    IDGGSKernel *pKernel=CreateKernelObj(gridType);

    //调用方法将code转为coord
    pKernel->decode(code,coord);

    //释放结构体
    DestroyKernelObj(pKernel);
}

/// <summary>
/// 经纬度转格网编码，使用IDGGSKernel的encode方法
/// </summary>
/// <param name="code">格网编码</param>
/// <param name="coord">经纬度结构体</param>
/// <param name="gridType">格网类型</param>
void encode(GeoCoord coord, DGGSElementCode &code, DGGSGridType gridType)
{
    // 初始化结构体，参数为格网类型：DGGS_ISEA4H,DGGS_ISEA4T,DGGS_ISEA4D
    IDGGSKernel *pKernel=CreateKernelObj(gridType);

    //调用方法将coord转为将code
    //注意：code需要提前设定好层级及类型
    /*
        * DGGSElementCode code;
        * code.level=8;
        * DGGSElementType elementType = DGGSElementType::Cell;  //DGGSElementType类型主要有Cell、Vertex、Edge等，详细查看DGGSDefine
        * code.elementType= elementType;
    */

    pKernel->encode(coord,code);

    //释放结构体
    DestroyKernelObj(pKernel);
}

/// <summary>
/// 拓扑查询，使用IDGGSKernel的query方法
/// </summary>
/// <param name="topoType">拓扑查询类型：相邻格点，相邻格边、相邻格元、父格网、子格网、兄弟格网</param>
/// <param name="code">格网编码</param>
/// <param name="result">迭代器，用于存储拓扑查询结构</param>
/// <param name="resultCount">用于存储拓扑查询的数量</param>
#include<iostream>
void query(DGGSTopoType topoType,DGGSElementCode code,DGGSElementCodeIter *&result,int &resultCount,DGGSGridType gridType)
{
    // 初始化结构体，参数为格网类型：DGGS_ISEA4H,DGGS_ISEA4T,DGGS_ISEA4D
    IDGGSKernel *pKernel=CreateKernelObj(gridType);

    // 调用IDGGSKernel的query方法
    pKernel->query(topoType,code,result,resultCount);

    //释放结构体
    DestroyKernelObj(pKernel);
}


/// <summary>
/// 获取所有格网的边界点坐标组，使用IDGGSKernel的query和decode，综合使用
/// </summary>
/// <param name="gridType">格网类型</param>
/// <param name="elementType">要素类型</param>
/// <param name="level">层级</param>
bool getALLCodeBound(DGGSGridType gridType,DGGSElementType elementType,int level)
{
    // 实例一个kernel实体，用于编码转化和拓扑查询
    IDGGSKernel *pkernel= CreateKernelObj(gridType);

    //计算行列数的最大值
    long long int rowSize= rowMaxSize(level);
    long long int colSize= fColMaxSize(level,gridType);//面的最大列数

    for(int b=1;b<10;b++)//遍历十个基菱形
        for(int row=0;row<rowSize;row++)//遍历所有行
            for(int col=0;col<colSize;col++)//遍历所有列
            {
                //定义一个临时的格元编码
                DGGSElementCode code;
                code.elementType=elementType;
                code.basePartition=b;
                code.row=row;
                code.col=col;

                //使用query查询这个格元所有边界点坐标
                DGGSElementCodeIter* boundPoints= nullptr;
                int pointCount=0;
                pkernel->query(DGGSTopoType::RelativeVertexes,code,boundPoints,pointCount);

                //使用decode将边界点的格点编码转化为经纬度
                DGGSElementCodeIter*tempIter=boundPoints;
                while(tempIter!= nullptr)
                {
                    GeoCoord coord{};
                    pkernel->decode(tempIter->code,coord);
                    std::cout<<"("<<coord.lon<<","<<coord.lat<<")";
                    tempIter=tempIter->next;
                }
                delete[]boundPoints;

                std::cout<<std::endl;
            }

    return true;
}

int main()
{
    DGGSGridType gridType=DGGSGridType::DGGS_ISEA4H;
    int level =5;
    DGGSElementType elementType=DGGSElementType::Cell;

    GeoCoord coord{45, 25};
    DGGSElementCode code;
    code.level=level;
    code.elementType=elementType;

    //经纬度转格网编码
    encode(coord,code,gridType);
    std::cout<<code.basePartition<<" "<<code.row<<" "<<code.col<<std::endl;

    //格网编码转经纬度
    code.row+=1;
    decode(code,coord,gridType);
    std::cout<<coord.lon<<" "<<coord.lat<<std::endl;

    //拓扑查询
    DGGSElementCodeIter *result= nullptr;
    int resultCount=0;
    DGGSTopoType topoType=DGGSTopoType::RelativeCells;
    query(topoType,code,result,resultCount,gridType);

    auto tempIter = result;
    while (tempIter!= nullptr)
    {
        std::cout<<tempIter->code.basePartition<<" "<<tempIter->code.row<<" "<<tempIter->code.col<<std::endl;
        tempIter=tempIter->next;
    }

    delete[]result;


    return 0;
}



